﻿using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using Assets.Scripts.TDuResource;
using Assets.Scripts.TDuVRUI;
using Pvr_UnitySDKAPI;

namespace Assets.Scripts.TDu3DWork
{
    class TDuSceneBaseWorker : UnityEngine.Object
    {
        //配置;
        public TDuSceneCfg m_sceneCfg;

        //动画
        public Animation m_animation;

        //声音
        public TDuAudioPlayer m_audioPlayer;

        //绘制
        public GameObject m_mainCanvas;
        public GameObject m_popupCanvas;
        //public GameObject m_TipPictureCanvas;
        //public GameObject m_VideoWndCanvas;

        //UI管理;
        public TDuUIManager m_uiManager;

        //配置路径;
        protected string m_strCfgUrl;

        //高亮组件开关
        private bool m_bHilightObject;

        //模型容器;
        public Transform m_modelContainer;

        //主相机或头盔
        public GameObject m_mainCamera;

        //VR或3D;
        protected bool m_bIsVR;

        //传送点;
        public GameObject m_teleportPoint;
        public LineRenderer m_teleportLine;
        public bool IsBezierCurve = true;
        public GameObject m_teleportManager;

        //vr手柄;
        public GameObject m_controller0;
        public GameObject m_controller1;
        public GameObject m_currentController;
        public GameObject m_headSet;
        public GameObject m_leftEye;
        public GameObject m_rightEye;
        public GameObject m_rayLine;
        public GameObject m_dot;
        public GameObject m_controller1Center;

        //手
        public GameObject m_leftHand;
        public GameObject m_rightHand;
        public GameObject m_leftHandCenter;
        public GameObject m_rightHandCenter;

        //shell命令交互事件和委托;
        public delegate void shellEventHandler(UnityEngine.Object sender, TDuShellEventArgs args);
        public event shellEventHandler shellHandler;

        //后置动作交互事件和委托;
        public delegate void postActionEventHandler(UnityEngine.Object sender, TDuPostEventArgs args);
        public event postActionEventHandler postActionHandler;

        //VR设备交互事件和委托;
        public delegate void vrControllerEventHandler(UnityEngine.Object sender, TDuVRControllerEventArgs args);
        public event vrControllerEventHandler controllerHandler;

        public TDuSceneBaseWorker( string strCfgUrl )
        {
            m_sceneCfg = new TDuSceneCfg();
            m_bHilightObject = true;           
            m_strCfgUrl = strCfgUrl;
            m_bIsVR = false;
            m_uiManager = new TDuUIManager();
            m_audioPlayer = GameObject.Find("AudioSourceMgr").AddComponent<TDuAudioPlayer>();
        }

        public TDuSceneBaseWorker()
        {
            m_sceneCfg = new TDuSceneCfg();
            m_bHilightObject = true;
            m_strCfgUrl = "";
            m_bIsVR = false;
            m_uiManager = new TDuUIManager();
            m_audioPlayer = GameObject.Find("AudioSourceMgr").AddComponent<TDuAudioPlayer>();
        }

        //配置加载与解析;
        public bool parsingSceneCfg()
        {
            if (!m_sceneCfg.loadSceneCfg(m_strCfgUrl))
                return false;

            return m_sceneCfg.readSceneCfg();
        }

        public void initComponets()
        {
            //添加高亮组件和碰撞组件;
            if(TDuProfile.Instance.m_profile.modelName== "模块检测model")
            {
                m_modelContainer = GameObject.Find("TDuRoot001").GetComponent<Transform>();
            }
            else
            {
                m_modelContainer = GameObject.Find(TDuProfile.Instance.m_profile.modelName).GetComponent<Transform>();
            }
            
            if (m_bHilightObject && m_modelContainer )
            {
                foreach (Transform child in m_modelContainer)
                {
                    child.gameObject.AddComponent<HighlightableObject>();
                    //child.gameObject.AddComponent<BoxCollider>();

                    //为组件或工具添加刚体, 当手柄与组件和刚体碰撞时,进入OnTriggerEnter函数                    
                    if (child.name.Contains("tool") || child.name.Contains("assemble"))
                    {
                        Rigidbody gd = child.gameObject.AddComponent<Rigidbody>();
                        gd.isKinematic = true;                        
                    }
                    
                    if (child.childCount > 0)
                        findChildRecurrent(child);
                }
            }

            //获取动画组件;            
            m_animation = GameObject.Find(TDuMainEntry.m_profile.AnimationObjName).GetComponent<Animation>();
            if (m_animation != null)
                m_animation.playAutomatically = true;

            Debug.Log("[Output]------Find Model's container:" + m_modelContainer);            
        }

        public void initCamera()
        {
            //获取相机
            m_mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
            //添加高亮特殊组件;
            if (m_mainCamera != null)
                m_mainCamera.AddComponent<HighlightingEffect>();

            Debug.Log("[Output]------Find Camera:" + m_mainCamera);
        }

        public void initUI()
        {
            m_mainCanvas = GameObject.Find("MainCanvas");
            if (m_mainCanvas)
            {
                m_mainCanvas.transform.localScale = new Vector3(0.001f, 0.001f, 0.001f);
            }

            m_popupCanvas = GameObject.Find("PopupCanvas");
            if( m_popupCanvas)
                m_popupCanvas.transform.localScale = new Vector3(0.001f, 0.001f, 0.001f);
            m_popupCanvas.SetActive(false);
            //m_TipPictureCanvas = GameObject.Find("TipPictureCanvas");
            //if (m_TipPictureCanvas)
            //    m_TipPictureCanvas.transform.localScale = new Vector3(0.001f, 0.001f, 0.001f);

            //m_VideoWndCanvas = GameObject.Find("VideoWndCanvas");
            //if (m_VideoWndCanvas)
            //    m_VideoWndCanvas.transform.localScale = new Vector3(0.001f, 0.001f, 0.001f);
        }
        public IEnumerator initVRDevice()
        {
            
            //获取VR手柄;
            m_controller0 = GameObject.Find("Pvr_UnitySDK/ControllerManager/PvrController0");
            m_controller1 = GameObject.Find("Pvr_UnitySDK/ControllerManager/PvrController1");
            m_headSet = GameObject.Find("Pvr_UnitySDK/Head");
            m_leftEye = GameObject.Find("Pvr_UnitySDK/Head/LeftEye");
            m_rightEye = GameObject.Find("Pvr_UnitySDK/Head/RightEye");

            //手柄射线;
            if( m_controller0)
            { 
                m_currentController = m_controller0;
            }

            //头盔;
            if ( m_headSet)
            {
                m_headSet.SetActive(true);
                if( m_leftEye )
                    m_leftEye.AddComponent<HighlightingEffect>();
                if (m_rightEye)
                    m_rightEye.AddComponent<HighlightingEffect>();
            }
            
            if (Pvr_UnitySDKManager.SDK.isHasController)
            {
                Pvr_ControllerManager.PvrServiceStartSuccessEvent += ServiceStartSuccess;
                Pvr_ControllerManager.SetControllerStateChangedEvent += ControllerStateListener;
                Pvr_ControllerManager.ControllerStatusChangeEvent += CheckControllerStateForGoblin;
            }

            //给手柄添加碰撞检测
            yield return new WaitUntil(() => m_controller0.transform.Find("controller").transform.childCount>0);
            yield return new WaitUntil(() => m_controller1.transform.Find("controller").transform.childCount>0);

            if (m_controller0)
            {
                Debug.Log("当前存在" + m_controller0.transform.Find("controller"));
                //Debug.Log("当前存在"+ m_controller0.transform.Find("controller").childCount);

                //添加碰撞器;
                GameObject leftHandModel = m_controller0.transform.Find("controller").transform.GetChild(0).gameObject;
                //GameObject leftHandModel = GameObject.Find("Neo2_L(Clone)").gameObject;
                leftHandModel.AddComponent<Rigidbody>().isKinematic = true;
                //MeshCollider bc = leftHandModel.AddComponent<MeshCollider>();
                //bc.convex = true;
                //bc.isTrigger = true;

                //添加脚本;
                //TDuTriggerScript tts = leftHandModel.AddComponent<TDuTriggerScript>();
                //tts.m_hand = leftHandModel/*.transform.parent.gameObject*/;
                ////tts.m_referenceObject = m_leftHandCenter;
                //tts.m_iHand = 0;
            }

            if (m_controller1)
            {
                GameObject rightHandModel = m_controller1.transform.Find("controller").transform.GetChild(0).gameObject;
                m_controller1Center = m_controller1.transform.Find("start").gameObject;
                rightHandModel.AddComponent<Rigidbody>().isKinematic = true;
                //MeshCollider bc = rightHandModel.AddComponent<MeshCollider>();
                //bc.convex = true;
                //bc.isTrigger = true;

                //添加脚本;
                //TDuTriggerScript tts = rightHandModel.AddComponent<TDuTriggerScript>();
                //tts.m_hand = rightHandModel/*.transform.parent.gameObject*/;

                //tts.m_referenceObject = m_controller1Center;
                ////tts.m_referenceObject = m_rightHandCenter;
                //tts.m_iHand = 1;
            }

            Debug.Log("[Output]------Find head" + m_headSet);
        }
        void OnDestroy()
        {
            Pvr_ControllerManager.PvrServiceStartSuccessEvent -= ServiceStartSuccess;
            Pvr_ControllerManager.PvrControllerStateChangedEvent -= ControllerStateListener;
            Pvr_ControllerManager.ChangeMainControllerCallBackEvent -= CheckControllerStateForGoblin;
        }
        public void initHands()
        {
            m_leftHand = GameObject.Find("TDuLefthand");
            m_rightHand = GameObject.Find("TDuRightthand");

            if ( m_leftHand)
            {
                //添加碰撞器;
                BoxCollider bc = m_leftHand.gameObject.AddComponent<BoxCollider>();
                bc.isTrigger = true;

                //添加脚本;
                TDuTriggerScript tts = m_leftHand.gameObject.AddComponent<TDuTriggerScript>();
                tts.m_hand = m_leftHand;
                tts.m_referenceObject = m_leftHandCenter;
                tts.m_iHand = 0;
            }

            if( m_rightHand)
            {
                BoxCollider bc = m_rightHand.gameObject.AddComponent<BoxCollider>();
                bc.isTrigger = true;

                //添加脚本;
                TDuTriggerScript tts = m_rightHand.gameObject.AddComponent<TDuTriggerScript>();
                tts.m_hand = m_rightHand;
                tts.m_referenceObject = m_rightHandCenter;
                tts.m_iHand = 1;
            }
        }

        public void initTeleport()
        {
            m_teleportPoint = GameObject.Find("TDuPoint");

            if(m_teleportPoint)
            {
                if (m_teleportPoint.GetComponent<LineRenderer>())
                    m_teleportLine = m_teleportPoint.GetComponent<LineRenderer>();
                else
                    m_teleportLine = m_teleportPoint.AddComponent<LineRenderer>();
                m_teleportLine.SetColors(Color.blue, Color.blue);
                m_teleportLine.startWidth = 0.02f;
                m_teleportLine.numCapVertices = 5;
            }

            m_teleportPoint.SetActive(false);

            m_teleportManager = FindObjectOfType<Pvr_UnitySDKManager>().gameObject;
        }

        public void ServiceStartSuccess()
        {

            if ( Controller.UPvr_GetControllerState(0) == ControllerState.Connected && 
                Controller.UPvr_GetControllerState(1) == ControllerState.Connected)
            {
                Debug.Log("[Output]------In Start Success,Controller State Listener:" + Controller.UPvr_GetMainHandNess());
                if (Controller.UPvr_GetMainHandNess() == 0)
                {
                    m_currentController = m_controller0;
                }
                if (Controller.UPvr_GetMainHandNess() == 1)
                {
                    m_currentController = m_controller1;
                }
            }
            //else
            //{
            //    if (Controller.UPvr_GetControllerState(0) == ControllerState.Connected)
            //        m_currentController = m_controller0;
            //    else if (Controller.UPvr_GetControllerState(1) == ControllerState.Connected)
            //        m_currentController = m_controller1;
            //}

            //m_rayLine = m_currentController.transform.Find("ray_LengthAdaptive").gameObject;
            //if (m_rayLine)
            //    m_rayLine.SetActive(true);

            //m_dot = m_currentController.transform.Find("dot").gameObject;
            //if (m_dot)
            //    m_dot.SetActive(true);
        }

        public void ControllerStateListener(string data)
        {
            if (Controller.UPvr_GetControllerState(0) == ControllerState.Connected &&
                Controller.UPvr_GetControllerState(1) == ControllerState.Connected)
            {
                Debug.Log("[Output]------Controller State Listener:" + Controller.UPvr_GetMainHandNess());
                if (Controller.UPvr_GetMainHandNess() == 0)
                {
                    m_currentController = m_controller0;
                }
                if (Controller.UPvr_GetMainHandNess() == 1)
                {
                    m_currentController = m_controller1;
                }
            }
            else
            {
                if (Controller.UPvr_GetControllerState(0) == ControllerState.Connected)
                    m_currentController = m_controller0;
                else if (Controller.UPvr_GetControllerState(1) == ControllerState.Connected)
                    m_currentController = m_controller1;
            }

            m_rayLine = m_currentController.transform.Find("ray_LengthAdaptive").gameObject;
            if (m_rayLine)
                m_rayLine.SetActive(true);

            m_dot = m_currentController.transform.Find("dot").gameObject;
            if (m_dot)
                m_dot.SetActive(true);
        }

        public void CheckControllerStateForGoblin(string state)
        {
            m_headSet.SetActive(Convert.ToInt16(state) != 1);
        }

        public void findChildRecurrent(Transform _parent)
        {
            foreach (Transform cchild in _parent)
            {
                cchild.gameObject.AddComponent<HighlightableObject>();
                //cchild.gameObject.AddComponent<BoxCollider>();

                if (cchild.name.Contains("tool") || cchild.name.Contains("assemble"))
                {
                    Rigidbody gd = cchild.gameObject.AddComponent<Rigidbody>();
                    gd.isKinematic = true;
                }

                if (cchild.childCount != 0)
                    findChildRecurrent(cchild);
            }
        }

        //前置条件检测
        public bool checkVarPreCondition(List<ConditionState> _vecData)
        {

            bool bLogicAll = true;
            for (int iterPre = 0; iterPre < _vecData.Count; iterPre++)
            {
                if (_vecData[iterPre].eLogicType != LogicType.And && _vecData[iterPre].eLogicType != LogicType.Or)
                {
                    bLogicAll = false;
                    break;
                }
            }

            //逻辑比较 
            bool bFitAll = true;
            if (bFitAll)
            {
                bool bFirst = true;
                for (int iterPre = 0; iterPre < _vecData.Count; iterPre++)
                {
                    bool bFitItem = false;
                    string strVarName = _vecData[iterPre].strName;
                    foreach (var key in m_sceneCfg.vecVariableNode.Values)
                    {
                        if (strVarName == key.strVarNodeName)
                        {
                            double p = _vecData[iterPre].cDestValue.value(m_sceneCfg.vecVariableNode);
                            double p1 = Math.Abs(key.dVarCurValue - p);

                            switch (_vecData[iterPre].eEqualType)
                            {
                                case EqualType.Equal:
                                    bFitItem = p1 > 0.01 ? false : true;
                                    break;
                                case EqualType.Greater:
                                    bFitItem = key.dVarCurValue > p ? true : false;
                                    break;
                                case EqualType.GreaterEqual:
                                    bFitItem = key.dVarCurValue >= p ? true : false;
                                    break;
                                case EqualType.Less:
                                    bFitItem = key.dVarCurValue < p ? true : false;
                                    break;
                                case EqualType.LessEqual:
                                    bFitItem = key.dVarCurValue <= p ? true : false;
                                    break;
                                case EqualType.NotEqual:
                                    bFitItem = p > 0.01 ? true : false;
                                    break;
                                default:
                                    break;
                            }
                            break;
                        }
                    }

                    if (bFirst)
                    {
                        bFitAll = bFitItem;
                    }

                    if (_vecData[iterPre].eLogicType == LogicType.And)
                    {
                        bFitAll = bFitAll && bFitItem;
                        if (!bFitAll)
                            break;
                    }
                    else
                    {
                        bFitAll = bFitAll || bFitItem;
                    }
                    bFirst = false;
                }
            }
            else
            {
                double dCalRet = 0;
                for (int iterPre = 0; iterPre < _vecData.Count; iterPre++)
                {
                    string strVarName = _vecData[iterPre].strName;
                    bool bHaveVarNode = m_sceneCfg.vecVariableNode.ContainsKey(strVarName);
                    if (bHaveVarNode)
                    {
                        switch (_vecData[iterPre].eLogicType)
                        {
                            case LogicType.Add:
                                dCalRet = dCalRet + m_sceneCfg.vecVariableNode[strVarName].dVarCurValue;
                                break;
                            case LogicType.Sub:
                                dCalRet = dCalRet - m_sceneCfg.vecVariableNode[strVarName].dVarCurValue;
                                break;
                        }
                        break;
                    }
                }
                bFitAll = (dCalRet > 0.0);
            }

            return bFitAll;
        }

        //设置相机视点;
        public bool setViewPort( string strViewName )
        {
            bool bRes = false;

            ViewPort resViewport;
            resViewport.arr3Rota = new float[3];
            resViewport.arr3Pos  = new float[3];
 
            foreach( ViewPort viewport in m_sceneCfg.vecViewPorts)
            {
                if( viewport.strViewPortName == strViewName)
                {
                    resViewport = viewport;
                    bRes = true;
                    break;
                }
            }

            if ( !bRes )
                return false;

            Vector3 vecPos = new Vector3(-resViewport.arr3Pos[0], resViewport.arr3Pos[2], -resViewport.arr3Pos[1]);
            m_mainCamera.transform.position = vecPos;

            Vector3 vecRotation = new Vector3(90 - resViewport.arr3Rota[0], resViewport.arr3Rota[2], resViewport.arr3Rota[1]);
            m_mainCamera.transform.rotation = Quaternion.Euler(vecRotation);
           
            return bRes;
        }

        public bool setViewPort( int index)
        {
            if (index < 0 && index >= m_sceneCfg.vecViewPorts.Count)
                return false;

            ViewPort resViewport = m_sceneCfg.vecViewPorts[index];

            Vector3 vecPos = new Vector3(-resViewport.arr3Pos[0], resViewport.arr3Pos[2], -resViewport.arr3Pos[1]);
            m_mainCamera.transform.position = vecPos;

            Vector3 vecRotation = new Vector3(90 - resViewport.arr3Rota[0], resViewport.arr3Rota[2], resViewport.arr3Rota[1]);
            m_mainCamera.transform.rotation = Quaternion.Euler(vecRotation);
            return true;
        }

        public bool setVrViewPort()
        {
            if (!m_headSet)
                return false;
            m_headSet.transform.parent.SetPositionAndRotation(TDuMainEntry.m_profile.vecViewPort.position, Quaternion.Euler(TDuMainEntry.m_profile.vecViewPort.rotation));
            Debug.Log("setVrViewPort");
            return true;
        }
        public static Vector3[] getBeizerPathPointList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint, int pointNum)
        {
            Vector3[] BeizerPathPointList = new Vector3[pointNum];
            for (int i = 1; i <= pointNum; i++)
            {
                float t = i / (float)pointNum;
                Vector3 point = getBeizerPathPoint(t, startPoint,
                    controlPoint, endPoint);
                BeizerPathPointList[i - 1] = point;
            }
            return BeizerPathPointList;
        }

        public static Vector3 getBeizerPathPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
        {
            return (1 - t) * (1 - t) * p0 + 2 * t * (1 - t) * p1 + t * t * p2;
        }

        public void drawLine()
        {
            Vector3 startPoint = m_currentController.transform.Find("start").position;
            Vector3 endPoint = m_currentController.transform.Find("dot").position;
            Vector3 controllerPoint = m_currentController.transform.Find("controller").position;
            if (!IsBezierCurve)
            {
                m_teleportLine.positionCount = 2;
                m_teleportLine.SetPosition(0, startPoint);
                m_teleportLine.SetPosition(1, endPoint);
            }
            else
            {
                float distance = Vector3.Distance(startPoint, endPoint);
                Vector3 controlPoint = startPoint + (startPoint - controllerPoint).normalized * distance / 1.6f;

                Vector3[] bcList = getBeizerPathPointList(startPoint, controlPoint, endPoint, 30);
                m_teleportLine.positionCount = bcList.Length + 1;
                m_teleportLine.SetPosition(0, startPoint);
                for (int i = 0; i < bcList.Length; i++)
                {
                    Vector3 v = bcList[i];
                    m_teleportLine.SetPosition(i + 1, v);
                }
            }
        }

        public void moveCameraPrefab(Vector3 target)
        {
            m_teleportManager.transform.position = new Vector3(target.x, target.y/* + 1.67f*/, target.z);
        }

        //后置动作处理
        public virtual void onPostAction( TDuPostEventArgs e)
        {
            if( postActionHandler != null )
            {
                postActionHandler(this, e);
            }
        }

        //adb shell命令处理
        public virtual void onShellAction( TDuShellEventArgs e)
        {
            if( shellHandler != null)
            {
                shellHandler(this, e);
            }
        }

        //vr手柄交互处理;
        public virtual void onVRControllerAction( TDuVRControllerEventArgs e)
        {
            if(controllerHandler != null)
            {
                controllerHandler(this, e);
            }
        }

        //高亮开关设置
        public void setHighlightObject(bool bHighlightObject) { m_bHilightObject = bHighlightObject; }
        public bool getHighlightObject() { return m_bHilightObject; }

        //文件路径设置;
        public void setCfgPath(string strCfgPath) { m_strCfgUrl = strCfgPath; }
        public string getCfgPath() { return m_strCfgUrl; }

        //
        public void setVROr3D( bool bIsVR) { m_bIsVR = bIsVR; }
        public bool getVROr3D( ) { return m_bIsVR; }
    }
}
